import miniSdk from 'mini_program_gizwits_sdk';
import { IProduct, getItemForPk } from '@/config/product';
import { getScanServices } from '@/config/template';
import deviceListModal from '@/models/deviceList';
import deviceDataModal from '@/models/deviceData';
import { isSameDevice, deviceIsBleConnect, deviceIsWAN } from '../index';

interface IGizwitsSDKProps {
  deviceList: IDevice[];
  isInit: boolean;
}

interface IProductInfo {
  productKey: string;
  productSecrets: string;
}

interface IDeviceStatusParam {
  device: IDevice;
  attrs?: string[];
}

export interface ISetDeviceOnboardingDeployProps {
  ssid: string;
  password: string;
  timeout: number;
  isBind?: boolean;
  mode?: 0 | 3; // 0 AP 3 BLE
  softAPSSIDPrefix: string;
}

interface ISDKInitParam {
  appID: string;
  appSecret: string;
  productInfo: IProductInfo[];
  cloudServiceInfo: IServiceInfo;
  token: string;
  uid: string;
  offlineThreshold?: boolean;
  needInitBle: boolean;
}

class GizwitsSDK implements IGizwitsSDKProps {
  isInit = false;

  sdk: miniSdk | null = null;

  deviceList: IDevice[] = [];

  bleDeviceList: IDevice[] = [];

  init(params: ISDKInitParam) {
    console.log('初始化SDK');
    if (!this.sdk) {
      this.sdk = new miniSdk(params);
      if (params.needInitBle) {
        this.sdk.initBle().then(res => {
          console.log('SDK 蓝牙初始化结果', res);
          if (res.success) {
            this.isInit = true;
            this.startAutoScanService();
          }
        });
      }
      this.sdk.addEventListener('GizDeviceListNotifications', this.handleDeviceListChanged);
      this.sdk.addEventListener('GizDeviceAttrsNotifications', this.handleDevicesAttrsChanged);
      this.sdk.addEventListener('onScanListChange', this.handleScanListChange);

      this.getBoundDevices();
    } else {
      this.sdk.reInit(params);
    }

    return { succeed: true };
  }

  checkCanCallSDK = () => {
    if (this.sdk && this.isInit) {
      return { success: true };
    } else {
      return { success: false, message: 'SDK Not Init' };
    }
  };

  // getSDKBindDeviceList = () => {
  //   return new Promise((resolve) => {
  //     this.sdk.getBindingList().then((r) => {
  //       setTimeout(() => {
  //         resolve(r);
  //       }, 100);
  //     });
  //   });
  // }

  deviceSafetyRegister = async ({ mac, productKey }: IDevice) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk!.deviceSafetyRegister({ mac, productKey });
    }
    return res;
  };

  getBoundDevices = async () => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      await this.sdk!.getBindingList();
      return { success: true, data: { devices: this.sdk!.deviceList } };
    }
    return res;
  };

  write = async (device: IDevice, attrs: any) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk!.write(device, attrs);
    }
    return res;
  };

  writeBigData = async (device: IDevice, data: number[]) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk?.writeBigData(device, data);
    }
    return res;
  };

  setDeviceOnboardingDeploy = async (params: ISetDeviceOnboardingDeployProps) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk!.setDeviceOnboardingDeploy(params);
    }
    return res;
  };

  stopDeviceOnboardingDeploy = async () => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk!.stopDeviceOnboardingDeploy();
    }
    return res;
  };

  bindRemoteDevice = async ({ mac, productKey }: { mac: string; productKey: string }) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk!.bindRemoteDevice({ mac, productKey });
    }
    return res;
  };

  // bindRemoteDevice = ({ mac, productKey }: { mac: string, productKey: string }) => {
  //   return new Promise((resolve) => {
  //     const res = this.checkCanCallSDK();
  //     if (res.success) {
  //       this.sdk.bindRemoteDevice({ mac, productKey }).then((r) => {
  //         setTimeout(() => {
  //           resolve(r);
  //         }, 100);
  //       });
  //     } else {
  //       resolve(res);
  //     }
  //   });
  // }

  unbindDevice = async (devices: IDevice[]) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      return this.sdk!.unbindDevice({ devices });
    }
    return res;
  };

  setSubscribe = async ({ device, subscribed }: { device: IDevice; subscribed: boolean }) => {
    // console.log('setSubscribe', device);
    const res = this.checkCanCallSDK();
    if (res.success) {
      if (subscribed) {
        const subscribeRes = await this.sdk?.subscribe(device, 'WAN');
        console.log('setSubscribe', subscribeRes);
        return subscribeRes;
      } else {
        const unsubscribeRes = await this.sdk?.unSubscribe(device);
        return unsubscribeRes;
      }
    }
    return res;
  };

  connectBleDevice = async device => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      const d = this.bleDeviceList.find(i => isSameDevice(i, device));
      // 设备是在设备
      if (d && d.isBleOnline && !deviceIsBleConnect(d)) {
        return this.sdk?.subscribe(device, 'BLE');
      }
      return { success: false };
    }
    return res;
  };

  disconnectBleDevice = async device => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      const d = this.deviceList.find(i => isSameDevice(i, device));
      // 设备是在设备
      if (deviceIsBleConnect(d)) {
        // 因为不是BLE的话，sdk走的逻辑是解除socket订阅，这里一定要判断下
        return this.sdk?.unSubscribe(d);
      }
      return { success: false };
    }
    return res;
  };

  getDeviceStatus = async ({ device, attrs }: IDeviceStatusParam) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      /**
       * 如果 attrs 没有指定
       * 则到产品配置中去找
       * 如果也找不到就查所有
       */
      try {
        if (!attrs || attrs?.length === 0) {
          const productInfo: IProduct = getItemForPk(device.productKey);
          console.log('getDeviceStatus attrs', attrs, productInfo.dpQueryKeys);
          if (productInfo && productInfo.dpQueryKeys) {
            attrs = productInfo.dpQueryKeys;
          }
        }
      } catch (error) {}
      return this.sdk!.getDeviceStatus(device, attrs);
    }
    return res;
  };

  handleDeviceListChanged = deviceList => {
    console.log('handleDeviceListChanged', deviceList);
    const devices = deviceList.map(device => {
      device.netStatus = device.isOnline ? 1 : 0;
      device.isSubscribed = deviceIsWAN(device); // 这里对应原生sdk的逻辑，订阅只是代表wifi的订阅，其他连接方式另外判断
      if (device.isSubscribed && device.isOnline) {
        device.netStatus = 2;
      } else if (deviceIsBleConnect(device) && device.isBleOnline) {
        device.netStatus = 2;
      }
      return device;
    });
    this.deviceList = devices;
    deviceListModal.setSdkDeviceList(this.deviceList);
  };

  handleDevicesAttrsChanged = ({ device, data }) => {
    console.log('handleDevicesChanged', device, data);
    if (data && data.isOnline !== undefined) {
      // 更新设备列表
      const targetDevice = this.deviceList.find(i => isSameDevice(i, device));
      if (targetDevice) {
        targetDevice.isOnline = data.isOnline;
        device.netStatus = device.isOnline ? 1 : 0;
        device.isSubscribed = deviceIsWAN(targetDevice);
        if (device.isSubscribed && targetDevice.isOnline) {
          targetDevice.netStatus = 2;
        } else if (deviceIsBleConnect(device) && device.isBleOnline) {
          device.netStatus = 2;
        }
        deviceListModal.updateNetStatus(targetDevice);
      }
    } else {
      deviceDataModal.deviceReportData({ device, data });
    }
  };

  handleScanListChange = bleDeviceList => {
    console.log('handleScanListChange', bleDeviceList);
    this.bleDeviceList = bleDeviceList;
    // deviceListModal.setBleDeviceList([{ mac: '7cdfa1b9cd3c', productKey: "3f4318c8c2144ce9a58ece1a404146b5", isBleOnline: true, connectType: 'NONE', bleWorkStatus: 1 }]);
    deviceListModal.setBleDeviceList(this.bleDeviceList);
  };

  scanBleDevice = async (delay?: number) => {
    const res = this.checkCanCallSDK();
    if (res.success) {
      const result = await this.sdk?.scanBleDevice(delay || 6000);
      console.log('scanBleDevice', result);
      if (result && result.success) {
        this.handleScanListChange(result.data);
      }
      return result;
    }
    return res;
  };

  stopScanBleDevice() {
    const res = this.checkCanCallSDK();
    if (res.success) {
      this.sdk?.stopScanBleDevice();
    }
  }

  startAutoScan() {
    const res = this.checkCanCallSDK();
    if (res.success) {
      this.startAutoScanService();
    }
  }

  startAutoScanService() {
    const services = getScanServices();
    console.log('startAutoScanService', services);
    if (services) {
      this.sdk?.startAutoScan(services);
    } else {
      this.sdk?.startAutoScan();
    }
  }

  stopAutoScan() {
    const res = this.checkCanCallSDK();
    if (res.success) {
      this.sdk?.stopAutoScan();
    }
  }
}

const sdk = new GizwitsSDK();

export default sdk;
